home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bint / b2uni.c < prev    next >
C/C++ Source or Header  |  1988-11-24  |  10KB  |  390 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2.  
  3. /*
  4.   $Header: b2uni.c,v 1.4 85/08/22 16:57:24 timo Exp $
  5. */
  6.  
  7. #include "b.h"
  8. #include "b0fea.h"
  9. #include "b1obj.h"
  10. #include "b2par.h"
  11. #include "b2key.h"
  12. #include "b2syn.h"
  13. #include "b2nod.h"
  14. #include "b3env.h"
  15. #include "b3err.h"
  16. #include "b3sou.h" /* for permkey() */
  17.  
  18. /* ******************************************************************** */
  19. /*        unit                            */
  20. /* ******************************************************************** */
  21.  
  22. Visible bool unit_keyword() {
  23.     bool b; txptr tx0= tx;
  24.     b= how_to_keyword() || yield_keyword() || test_keyword();
  25.     tx= tx0;
  26.     return b;
  27. }
  28.  
  29. Hidden value formlist, sharelist;
  30. Hidden envtab reftab; 
  31. Visible literal idf_cntxt;
  32.  
  33. Forward bool is_howto_unit(), is_yield_unit(), is_test_unit();
  34. Forward parsetree unicmd_suite(), ref_suite();
  35.  
  36. Visible parsetree unit(heading) bool heading; {
  37.     parsetree v= NilTree;
  38.     if (!heading) {
  39.         lino= 1;
  40.         cntxt= In_unit;
  41.         release(uname); uname= Vnil;
  42.     }
  43.     if (!is_howto_unit(&v, heading) &&
  44.         !is_yield_unit(&v, heading) &&
  45.         !is_test_unit(&v, heading)
  46.        )
  47.         parerr(MESS(2800, "no unit keyword where expected"));
  48. #ifdef TYPE_CHECK
  49.     if (!heading) type_check(v);
  50. #endif
  51.     return v;
  52. }
  53.  
  54. /* ******************************************************************** */
  55. /*        howto_unit                        */
  56. /* ******************************************************************** */
  57.  
  58. Forward value hu_formals();
  59.  
  60. Hidden bool is_howto_unit(v, heading) parsetree *v; bool heading; {
  61.     if (how_to_keyword()) {
  62.         value kw, w, f;
  63.         txptr ftx, ttx;
  64.         if (cur_ilev != 0) parerr(MESS(2801, "unit starts with indentation"));
  65.         formlist= mk_elt(); 
  66.         skipsp(&tx);
  67.         kw= keyword(); 
  68.         release(uname); uname= permkey(kw, How);
  69.         if (in(kw, kwlist)) pprerr2(kw, MESS(2802, " is a reserved keyword"));
  70.         req(":", ceol, &ftx, &ttx);
  71.         idf_cntxt= In_formal;
  72.         f= hu_formals(ftx, kw); tx= ttx;
  73.         if (!is_comment(&w)) w= Vnil;
  74.         *v= node8(HOW_TO, copy(kw), f, w, NilTree, NilTree, Vnil, Vnil);
  75.         if (!heading) {
  76.             sharelist= mk_elt();
  77.             *Branch(*v, HOW_SUITE)= unicmd_suite();
  78.             reftab= mk_elt();
  79.             *Branch(*v, HOW_REFINEMENT)= ref_suite();
  80.             *Branch(*v, HOW_R_NAMES)= reftab;
  81.             release(sharelist);
  82.         }
  83.         release(formlist); 
  84.         return Yes;
  85.     }
  86.     return No;
  87. }
  88.  
  89. Hidden value hu_formals(q, kw) txptr q; value kw; {
  90.     value t, v, w;
  91.     skipsp(&tx);
  92.     if (Text(q) && is_tag(&t)) treat_idf(t);
  93.     else t= Vnil;
  94.     skipsp(&tx);
  95.     v= Text(q) ? hu_formals(q, keyword()) : Vnil;
  96.     w= node4(FORMAL, kw, t, v);
  97.     return w;
  98. }
  99.  
  100. /* ******************************************************************** */
  101. /*        yield_unit                        */
  102. /* ******************************************************************** */
  103.  
  104. Forward parsetree ytu_formals();
  105.  
  106. Hidden bool is_yield_unit(v, heading) parsetree *v; bool heading; {
  107.     if (yield_keyword()) {
  108.         parsetree f; value name, w, adicity;
  109.         txptr ftx, ttx;
  110.         if (cur_ilev != 0) parerr(MESS(2803, "unit starts with indentation"));
  111.         formlist= mk_elt(); 
  112.         skipsp(&tx);
  113.         req(":", ceol, &ftx, &ttx);
  114.         f= ytu_formals(ftx, 'y', &name, &adicity); tx= ttx;
  115.         if (!is_comment(&w)) w= Vnil;
  116.         *v= node9(YIELD, copy(name), adicity, f, w, NilTree,
  117.               NilTree, Vnil, Vnil);
  118.         if (!heading) {
  119.             sharelist= mk_elt();
  120.             *Branch(*v, FPR_SUITE)= unicmd_suite();
  121.             reftab= mk_elt();
  122.             *Branch(*v, FPR_REFINEMENT)= ref_suite();
  123.             *Branch(*v, FPR_R_NAMES)= reftab;
  124.             release(sharelist);
  125.         }
  126.         release(formlist); 
  127.         return Yes;
  128.     }
  129.     return No;
  130. }
  131.  
  132. /* ******************************************************************** */
  133. /*        test_unit                        */
  134. /* ******************************************************************** */
  135.  
  136. Hidden bool is_test_unit(v, heading) parsetree *v; bool heading; {
  137.     if (test_keyword()) {
  138.         parsetree f; value name, w, adicity;
  139.         txptr ftx, ttx;
  140.         if (cur_ilev != 0) parerr(MESS(2804, "unit starts with indentation"));
  141.         formlist= mk_elt();
  142.         skipsp(&tx);
  143.         req(":", ceol, &ftx, &ttx);
  144.         f= ytu_formals(ftx, 't', &name, &adicity); tx= ttx;
  145.         if (!is_comment(&w)) w= Vnil;
  146.         *v= node9(TEST, copy(name), adicity, f, w, NilTree,
  147.               NilTree, Vnil, Vnil);
  148.         if (!heading) {
  149.             sharelist= mk_elt();
  150.             *Branch(*v, FPR_SUITE)= unicmd_suite();
  151.             reftab= mk_elt();
  152.             *Branch(*v, FPR_REFINEMENT)= ref_suite();
  153.             *Branch(*v, FPR_R_NAMES)= reftab;
  154.             release(sharelist);
  155.         }
  156.         release(formlist); 
  157.         return Yes;
  158.     }
  159.     return No;
  160. }
  161.  
  162. /* ******************************************************************** */
  163.  
  164. #define FML_IN_FML MESS(2805, " is already a formal parameter or operand")
  165. #define SH_IN_FML  MESS(2806, " is already a formal parameter")
  166. #define SH_IN_SH   MESS(2807, " is already a shared identifier")
  167. #define REF_IN_FML MESS(2808, " is already a formal parameter")
  168. #define REF_IN_SH  MESS(2809, " is already a shared identifier")
  169. #define REF_IN_REF MESS(2810, " is already a refinement name")
  170.  
  171. Hidden Procedure treat_idf(t) value t; {
  172.     switch (idf_cntxt) {
  173.         case In_formal:    if (in(t, formlist)) pprerr2(t, FML_IN_FML);
  174.                 insert(t, &formlist);
  175.                 break;
  176.         case In_share:    if (in(t, formlist)) pprerr2(t, SH_IN_FML);
  177.                 if (in(t, sharelist)) pprerr2(t, SH_IN_SH);
  178.                 insert(t, &sharelist);
  179.                 break;
  180.         case In_ref:    if (in(t, formlist)) pprerr2(t, REF_IN_FML);
  181.                 if (in(t, sharelist)) pprerr2(t, REF_IN_SH);
  182.                 break;
  183.         case In_ranger: break;
  184.         default:    break;
  185.     }
  186. }
  187.  
  188. Forward parsetree fml_operand();
  189.  
  190. Hidden parsetree ytu_formals(q, yt, name, adic)
  191.     txptr q; char yt; value *name, *adic; {
  192.  
  193.     parsetree v1, v2, v3;
  194.     *name= Vnil;
  195.     idf_cntxt= In_formal;
  196.     v1= fml_operand(q);
  197.     skipsp(&tx);
  198.     if (!Text(q)) { /* zeroadic */
  199.         *adic= zero; 
  200.         if (nodetype(v1) == TAG) {
  201.             *name= *Branch(v1, TAG_NAME);
  202.             release(uname); uname= permkey(*name, Zer);
  203.          } else
  204.             pprerr(MESS(2811, "user defined functions must be tags"));
  205.         return v1;
  206.     }
  207.  
  208.     v2= fml_operand(q);
  209.     skipsp(&tx);
  210.     if (!Text(q)) { /* monadic */
  211.         *adic= one; 
  212.         if (nodetype(v1) == TAG) {
  213.             *name= *Branch(v1, TAG_NAME);
  214.             release(uname); uname= permkey(*name, Mon);
  215.         } else
  216.             pprerr(MESS(2812, "no monadic function name"));
  217.         if (nodetype(v2) == TAG) treat_idf(*Branch(v2, TAG_NAME));
  218.         return node4(yt == 'y' ? MONF : MONPRD, *name, v2, Vnil);
  219.     }
  220.  
  221.     v3= fml_operand(q);
  222.     /* dyadic */
  223.     *adic= mk_integer(2);
  224.     if (nodetype(v2) == TAG) {
  225.         *name= *Branch(v2, TAG_NAME);
  226.         release(uname); uname= permkey(*name, Dya);
  227.     } else
  228.         pprerr(MESS(2813, "no dyadic function name"));
  229.     upto(q, "dyadic formal formula");
  230.     if (nodetype(v1) == TAG) treat_idf(*Branch(v1, TAG_NAME));
  231.     if (nodetype(v3) == TAG) treat_idf(*Branch(v3, TAG_NAME));
  232.     return node5(yt == 'y' ? DYAF : DYAPRD, v1, *name, v3, Vnil);
  233. }
  234.  
  235. Hidden parsetree fml_operand(q) txptr q; {
  236.     value t;
  237.     skipsp(&tx);
  238.     if (nothing(q, "formal operand")) return NilTree;
  239.     else if (is_tag(&t)) return node2(TAG, t);
  240.     else if (open_sign()) return compound(q, idf);
  241.     else {
  242.         parerr(MESS(2814, "no formal operand where expected"));
  243.         tx= q;
  244.         return NilTree;
  245.     }
  246. }
  247.  
  248. /* ******************************************************************** */
  249. /*        unit_command_suite                    */
  250. /* ******************************************************************** */
  251.  
  252. Forward parsetree ucmd_seq();
  253.  
  254. Forward bool share();
  255.  
  256. Hidden parsetree unicmd_suite() {
  257.     if (ateol()) 
  258.         return ucmd_seq(0, Yes);
  259.     else {
  260.         parsetree v; value c; intlet l= lino;
  261.         suite_command(&v, &c);
  262.         return node5(SUITE, mk_integer(l), v, c, NilTree);
  263.     }
  264. }
  265.  
  266. Hidden parsetree ucmd_seq(cil, first) intlet cil; bool first; {
  267.     value c; intlet level, l;
  268.     level= ilev(); l= lino;
  269.     if (is_comment(&c)) 
  270.         return node5(SUITE, mk_integer(l), NilTree, c,
  271.                 ucmd_seq(cil, first));
  272.     if ((level == cil && !first) || (level > cil && first)) {
  273.         parsetree v;
  274.         findceol();
  275.         if (share(ceol, &v, &c)) 
  276.             return node5(SUITE, mk_integer(l), v, c,
  277.                     ucmd_seq(level, No));
  278.         veli();
  279.         return cmd_suite(cil, first);
  280.     }
  281.     veli();
  282.     return NilTree;
  283.  
  284. Hidden bool share(q, v, c) txptr q; parsetree *v; value *c; {
  285.     if (share_keyword()) {
  286.         idf_cntxt= In_share;
  287.         *v= node2(SHARE, idf(q));
  288.         *c= tail_line();
  289.         return Yes;
  290.     }
  291.     return No;
  292. }
  293.  
  294.  
  295. /* ******************************************************************** */
  296. /*        refinement_suite                    */
  297. /* ******************************************************************** */
  298.  
  299. Hidden parsetree ref_suite() {
  300.     value name; bool t;
  301.     if (ilev() > 0) {
  302.         parerr(MESS(2815, "indentation where not allowed"));
  303.         return NilTree;
  304.     }
  305.     if ((t= is_tag(&name)) || is_keyword(&name)) {
  306.         parsetree v, s; value w, *aa, r;
  307.         skipsp(&tx);
  308.         if (Char(tx) != ':') {
  309.             release(name);
  310.             tx= fcol();
  311.             veli(); return NilTree;
  312.         }
  313.         /* lino= 1; cntxt= In_ref; */
  314.         tx++;
  315.         if (t) {
  316.             idf_cntxt= In_ref;
  317.             treat_idf(name);
  318.         }
  319.         if (in_env(reftab, name, &aa)) pprerr2(name, REF_IN_REF);
  320.         findceol();
  321.         if (!is_comment(&w)) w= Vnil;
  322.         s= cmd_suite(0, Yes);
  323.         v= node6(REFINEMENT, name, w, s, Vnil, Vnil);
  324.         e_replace(r= mk_ref(v), &reftab, name);
  325.         release(r);
  326.         *Branch(v, REF_NEXT)= ref_suite();
  327.         return v;
  328.     } 
  329.     veli();
  330.     return NilTree;
  331. }
  332.  
  333. /* ******************************************************************** */
  334. /*        collateral, compound                    */
  335. /* ******************************************************************** */
  336.  
  337. Hidden parsetree n_collateral(q, n, base)
  338.     txptr q; intlet n; parsetree (*base)(); {
  339.  
  340.     parsetree v, w; txptr ftx, ttx;
  341.     if (find(",", q, &ftx, &ttx)) {
  342.         w= (*base)(ftx); tx= ttx;
  343.         v= n_collateral(q, n+1, base);
  344.     } else {
  345.         w= (*base)(q);
  346.         if (n == 1) return w;
  347.         v= mk_compound(n);
  348.     }
  349.     *Field(v, n-1)= w;
  350.     return n > 1 ? v : node2(COLLATERAL, v);
  351. }
  352.  
  353. Visible parsetree collateral(q, base) txptr q; parsetree (*base)(); {
  354.     return n_collateral(q, 1, base);
  355. }
  356.  
  357. Visible parsetree compound(q, base) txptr q; parsetree (*base)(); {
  358.     parsetree v; txptr ftx, ttx;
  359.     req(")", q, &ftx, &ttx);
  360.     v= (*base)(ftx); tx= ttx;
  361.     return node2(COMPOUND, v);
  362. }
  363.  
  364. /* ******************************************************************** */
  365. /*        idf, singidf                        */
  366. /* ******************************************************************** */
  367.  
  368. Hidden parsetree singidf(q) txptr q; {
  369.     parsetree v;
  370.     skipsp(&tx);
  371.     if (nothing(q, "identifier"))
  372.         v= NilTree;
  373.     else if (open_sign())
  374.         v= compound(q, idf);
  375.     else if (is_tag(&v)) {
  376.         treat_idf(v);
  377.         v= node2(TAG, v);
  378.     } else {
  379.         parerr(MESS(2816, "no identifier where expected"));
  380.         v= NilTree;
  381.     }
  382.     upto(q, "identifier");
  383.     return v;
  384. }
  385.  
  386. Visible parsetree idf(q) txptr q; {
  387.     return collateral(q, singidf);
  388. }
  389.